跳到主要内容

使用 react redux

React-ReduxRedux 官方为 React 应用设计的绑定库,用于在 React 组件中高效地访问和更新 Redux 状态。

它提供了两个核心 API:Providerconnect(或 Hooks API: useSelectoruseDispatch

一、创建 Redux Store

在使用 React-Redux 前,需要先创建 Redux 的全局 Store,通常通过 redux-thunk (RTK) 监护流程:

store.js
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice'; // 假设后续有切片

// 配置并导出 Store
export const store = configureStore({
reducer: {
counter: counterReducer, // 注册状态切片
},
});

二、 Provider :连接 React 应用与 React-Redux

ProviderReact-Redux 提供的组件,用于将 Redux store 注入到 React 应用的上下文,使得所有的子组件都可以通过 Hook (函数式组件) 或 connect (类式组件) 访问 Store。

使用 Provider 包裹在应用的最外层组件(如 App),并通过 store 属性传递创建好的的全局 store。

// index.js (入口文件)
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import { store } from './store'; // 之前创建的 store
import App from './App';

const root = React.createRoot(document.getElementById('root'));

root.render(
<Provider store={store}>
<App /> {/** 所有组件可通过 React-Redux 访问 Store */}
</Provider>,
);

三、 useSelector :从 Store 中读取状态

useSelectorReact-Redux 提供的 Hook,用于在函数组件中订阅 Store 的状态片段。当订阅的状态变化时,组件会自动重新渲染。

Counter.jsx
import { useSelector } from 'react-redux';

function Counter() {
// 从 store.state.counter 中获取 value
const counterValue = useSelector(state => state.counter.value);

return <div>当前计数:{counterValue}</div>;
}

1. 选择器优化

useSelector 默认使用浅比较判断状态是否变化。若选择器返回的新对象/数组(即使内容未变),可能导致组件不表渲染。

    1. 直接返回原始值(如数字、字符串)
    1. 使用 reselect 库的 createSelector 创建记忆化选择器(推荐复杂场景)
优化后
import { createSelector } from '@reduxjs/toolkit';

// 创建记忆选择器
const selectCounterValue = createSelector(
state => state.count, // 输入选择器
counter => counter.value, // 输出选择器(仅当 counter 变化时重新计算)
);

// 在组件中使用
const counterValue = useSelector(selectCounterValue);

四、 useDispatch:派发 Action 更新状态

useDispatchReact-Redux 提供的 Hook,用于获取 dispatch 函数,通过派发 Action 触发状态更新。

import { useDispatch } from 'react-redux';
import { increment, decrement, addByAmount } from './counterSlice';

function Counter() {
const dispatch = useDispatch(); // 获取 dispatch 函数

return (
<div>
<button onClick={() => dispatch(increment())}>+1</button>
<button onClick={() => dispatch(decrement())}>-1</button>
<button onClick={() => dispatch(addByAmount(5))}>+5</button>
</div>
);
}

五、完整的示例:计算器组件

Counter.jsx
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, addByAmount } from './counterSlice';

export function Counter() {
/** 读取状态 */
const counterValue = useSelector(state => state.counter.value);
const dispatch = useDispatch();

return (
<div>
<h2>计算器:{counterValue}</h2>
<button onClock={() => dispatch(increment())}>+1</button>
<button onClock={() => dispatch(decrement())}>-1</button>
<button onClock={() => dispatch(addByAmount(5))}>+5</button>
</div>
);
}

六、 与 connect API 对比

React-Redux 从 v7 开始推荐使用 Hooks API (useSelectoruseDispatch),而不是传统的 connect` API。

使用 HOOKS 的优势

  • 代码更简洁:不需要创建额外的函数
  • 更符合 React Hooks 设计:更容易与 React16.8+ 的 Hooks 特性集成
  • 组件更易读:状态获取和动作触发在同一个组件中,逻辑更集中
import { connect } from 'react-redux';

const mapStateToProps = state => ({
count: state.count.value,
});

const mapDispatchToProps = dispatch => ({
increment: () => dispatch(increment()),
decrement: () => dispatch(decrement()),
});

const Counter = ({ counter, increment, decrement }) => (
<div>
<h2>当前计数:{counter}</h2>
<button onClick={() => increment()}>+1</button>
<button onClick={() => decrement()}>-1</button>
</div>
);

export default connect(mapStateToProps, mapDispatchToProps)(Counter);